/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.octopeer.network;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.Observer;
import java.util.Vector;
import java.util.Observable;
import java.io.IOException;
import net.octopeer.main.OctopeerService;

/**
 *
 * @author andria
 */
public class Listener implements Observer {
    private Socket socket;

    /** This vector holds all connected clients.
     * May be used for broadcasting, etc. */
    private Vector peers;
    private ServerSocket lsocket;         //Server Socket
    private StartListenerThread slt;      //inner class

    /**
     * Represents each currently connected client.
     * @label initiates
     * @clientCardinality 1
     * @supplierCardinality 0..*
     */
    private Connection peerThread;
    
    /** Port number of Server. */
    private int port;
    private boolean listening;          //status for listening
    
    /** Octopeer properties */
    public OctopeerService oService;
    
    /**
     * 
     */
    public Listener() {
        this.peers = new Vector();
        this.port = 5555; //default port
        this.listening = false;
    }
    
    /**
     * 
     * @param port
     */
    public Listener(int port, OctopeerService oService) {
        this.peers = new Vector();
        this.port = port; //custom port
        this.listening = false;
        this.oService = oService;
    }
    
    /**
     * 
     */
    public void startListener() {
        if (!listening) {
            this.slt = new StartListenerThread();
            this.slt.start();
            this.listening = true;
        }
    }

    /**
     * 
     */
    public void stopListener() {
        if (this.listening) {
            this.slt.stopListenerThread();
		//close all connected clients//

            java.util.Enumeration e = this.peers.elements();
            while(e.hasMoreElements()) {
		Connection ct = (Connection)e.nextElement();
                ct.stopClient();
            }
            this.listening = false;
        }
    }
    
    //observer interface//
    /**
     * 
     * @param observable
     * @param object
     */
    public void update(Observable observable, Object object) {
        //notified by observables, do cleanup here//
        this.peers.removeElement(observable);
    }

    /**
     * 
     * @return
     */
    public int getPort() {
        return port;
    }

    /**
     * 
     * @param port
     */
    public void setPort(int port) {
        this.port = port;
    }
    
    /** This inner class will keep listening to incoming connections,
     *  and initiating a ClientThread object for each connection. 
     */
    private class StartListenerThread extends Thread {
        private boolean listen;

        /**
         * 
         */
        public StartListenerThread() {
            this.listen = false;
        }

        /**
         * 
         */
        @Override
        public void run() {
            this.listen = true;
            try {
                /**The following constructor provides a default number of
                 * connections -- 50, according to Java's documentation.
                 * An overloaded constructor is available for providing a 
                 * specific number, more or less, about connections. */

                Listener.this.lsocket = new ServerSocket(Listener.this.port);
                
                while (this.listen) {
                    //wait for client to connect//
                    Listener.this.socket = Listener.this.lsocket.accept();
                    System.out.println("Peer connected");
                    try {
                        Listener.this.peerThread = new Connection(Listener.this.socket, Listener.this.oService);
                        Thread t =  new Thread(Listener.this.peerThread);
                        Listener.this.peerThread.addObserver(Listener.this);
                        Listener.this.peers.addElement(Listener.this.peerThread);
                        t.start();
                    } catch (IOException ioe) {
                        //some error occured in ClientThread //
                    }
                }
            } catch (IOException ioe) {
                //I/O error in ServerSocket//
                this.stopListenerThread();
            }
        }

        /**
         * 
         */
        public void stopListenerThread() {
            try {
                Listener.this.lsocket.close();
            }
            catch (IOException ioe) {
                //unable to close ServerSocket
            }
            
            this.listen = false;
        }
    }
    
//    public static void main(String[] args) {
//        Listener l = new Listener();
//        l.startListener();;
//    }
}
